package org.bet.service;

import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import org.bet.dao.BioFeatureSetDao;
import org.bet.domain.BioFeatureEntry;
import org.bet.domain.BioFeatureSet;
import org.bet.exception.BETException;
import org.bet.exception.BETExceptionFactory;
import org.bet.loader.BioFeatureEntryParser;
import org.bet.loader.BioFeatureEntryParser.FormatType;
import org.bet.loader.BioFeatureSetLoader;
import org.bet.loader.BioFeatureSetLoader.DropTarget;
import org.bet.loader.DefaultBioFeatureSetLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BioFeatureSetService {
	@Autowired
	private BETExceptionFactory exceptionFactory;
	
	@Autowired
	private BioFeatureSetDao bioFeatureSetDao;
	
	@Resource
	private List<BioFeatureEntryParser> bioFeatureEntryParsers;
	
	private BioFeatureSetLoader bioFeatureSetLoader = new DefaultBioFeatureSetLoader();
	
	public List<BioFeatureEntryParser> getBioFeatureEntryParsers() {
		return bioFeatureEntryParsers;
	}

	public void setBioFeatureEntryParsers(
			List<BioFeatureEntryParser> bioFeatureEntryParsers) {
		this.bioFeatureEntryParsers = bioFeatureEntryParsers;
	}

	public int loadAndSaveBioFeaturSet(final BioFeatureSet target, String[] locations, FormatType formatType) throws BETException {
		try{
			// get entry parser
			BioFeatureEntryParser entryParser = findBioFeatureEntryParser(formatType);
			if(entryParser == null){
				throw exceptionFactory.createException("", new Object[]{ formatType });
			}
			
			// saveOrUpdate bioFeatureSet
			bioFeatureSetDao.saveOrUpdateBioFeatureSet(target);
			
			return bioFeatureSetLoader.load(locations, new DropTarget(){
				@Override
				public BioFeatureSet getTarget() {
					return target;
				}

				@Override
				public void dropEntries(Collection<BioFeatureEntry> entries) {
					bioFeatureSetDao.saveOrUpdateBioFeatureEntries(entries);
				}

				
			}, entryParser);
			
		}
		catch(Exception e){
			throw exceptionFactory.createException("error.bioFeatureSetService.loadAndSave", new Object[]{ target.getId() });
		}
	}

	private BioFeatureEntryParser findBioFeatureEntryParser(FormatType formatType) {
		for(BioFeatureEntryParser parser : bioFeatureEntryParsers){
			if(parser.supports(formatType)){
				return parser;
			}
		}
		return null;
	}

	public List<BioFeatureEntry> getAllBioFeatureEntriesOf(String featureSetId) throws BETException {
		try{
			return bioFeatureSetDao.getAllBioFeatureEntriesOf(featureSetId);
		}
		catch(Exception e){
			throw exceptionFactory.createException("error.bioFeatureSetService.getAllBioFeatureEntriesOf", new Object[]{ featureSetId });
		}
	}

	public BioFeatureSet getBioFeatureSet(String id) throws BETException {
		try{
			return bioFeatureSetDao.getBioFeatureSet(id);
		}
		catch(Exception e){
			throw exceptionFactory.createException("error.bioFeatureSetService.getBioFeatureSet", new Object[]{ id });
		}
	}

	public void saveOrUpdateBioFeatureSet(BioFeatureSet bioFeatureSet) throws BETException {
		try{
			bioFeatureSetDao.saveOrUpdateBioFeatureSet(bioFeatureSet);
		}
		catch(Exception e){
			throw exceptionFactory.createException("error.bioFeatureSetService.saveOrUpdateBioFeatureSet", new Object[]{ bioFeatureSet.getId() });
		}
		
	}


}
